package com.zhl.util;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;

/**
 * @author zhl
 * @Title: DingDingMsgSendUtils
 * @Description 钉钉消息发送工具类
 * 机器人发送消息频率限制：每个机器人每分钟最多发送20条。如果超过20条，会限流10分钟。
 * @date： 2020/10/21 14:44
 * @version： V1.0
 */
@Slf4j
public class DingDingMsgSendUtils {

    /**
     * 调用钉钉官方接口发送钉钉消息（旧版本，不需要配置安全设置）
     * @param accessToken
     * @param textMsg
     */
    private static void dealDingDingMsgSend(String accessToken, String textMsg) {
        HttpClient httpclient = HttpClients.createDefault();
        String WEBHOOK_TOKEN = "https://oapi.dingtalk.com/robot/send?access_token=" + accessToken;
        HttpPost httppost = new HttpPost(WEBHOOK_TOKEN);
        httppost.addHeader("Content-Type", "application/json; charset=utf-8");
        StringEntity se = new StringEntity(textMsg, "utf-8");
        httppost.setEntity(se);

        try {
            HttpResponse response = httpclient.execute(httppost);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                String result= EntityUtils.toString(response.getEntity(), "utf-8");
                log.info("【发送钉钉群消息】消息响应结果：" + JSON.toJSONString(result));
            }
        } catch (Exception e) {
            log.error("【发送钉钉群消息】error：" + e.getMessage(), e);
        }
    }

    /**
     * 调用钉钉官方接口发送钉钉消息（新版本，需要配置安全设置）
     * @param accessToken
     * @param secret
     * @param textMsg
     */
    private static void dealDingDingMsgSendNew(String accessToken, String secret, String textMsg) {
        Long timestamp = System.currentTimeMillis();
        String sign = getSign(secret, timestamp);
        String url = "https://oapi.dingtalk.com/robot/send?access_token=" + accessToken + "&timestamp=" + timestamp + "&sign=" + sign;
        try {
            log.info("【发送钉钉群消息】请求参数：url = {}, textMsg = {}", url, textMsg);
            String res = HttpUtil.post(url, textMsg);
            log.info("【发送钉钉群消息】消息响应结果：" + res);
        } catch (Exception e) {
            log.warn("【发送钉钉群消息】请求钉钉接口异常，errMsg = {}", e);
        }
    }

    /**
     * 计算签名
     * @param secret 密钥，机器人安全设置页面，加签一栏下面显示的SEC开头的字符
     * @param timestamp
     * @return
     */
    private static String getSign(String secret, Long timestamp){
        try {
            String stringToSign = timestamp + "\n" + secret;
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
            byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
            String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)),"UTF-8");
            log.info("【发送钉钉群消息】获取到签名sign = {}", sign);
            return sign;
        } catch (Exception e) {
            log.error("【发送钉钉群消息】计算签名异常，errMsg = {}", e);
            return null;
        }
    }

    /**
     * 发送钉钉群消息
     * @param accessToken
     * @param content
     */
    public static void sendDingDingGroupMsg(String accessToken, String content) {
        String textMsg = "{ \"msgtype\": \"text\", \"text\": {\"content\": \"" + content + "\"}}";
        dealDingDingMsgSend(accessToken, textMsg);
    }

    /**
     * 发送钉钉群消息（可以艾特人）
     * @param accessToken 群机器人accessToken
     * @param content 发送内容
     * @param atPhone 艾特人电话，如：13867400741,15608457257,15072328011
     */
    public static void sendDingDingGroupMsg(String accessToken, String content, String atPhone) {
        String textMsg = "{\n" +
                "    \"msgtype\": \"text\", \n" +
                "    \"text\": {\n" +
                "        \"content\": \""+ content +"\"\n" +
                "    }, \n" +
                "    \"at\": {\n" +
                "        \"atMobiles\": [\n" +
                "            " + atPhone +
                "        ], \n" +
                "        \"isAtAll\": false\n" +
                "    }\n" +
                "}";
        dealDingDingMsgSend(accessToken, textMsg);
    }

    /**
     * 发送钉钉群消息（link类型）
     * @param accessToken
     * @param title 消息标题
     * @param text 消息内容。如果太长只会部分展示
     * @param picUrl 图片URL
     * @param messageUrl 点击消息跳转的URL
     */
    public static void sendDingDingLinkGroupMsg(String accessToken, String title, String text, String picUrl, String messageUrl) {
        String textMsg = "{\n" +
                "    \"msgtype\": \"link\", \n" +
                "    \"link\": {\n" +
                "        \"text\": \""+text+"\", \n" +
                "        \"title\": \""+title+"\", \n" +
                "        \"picUrl\": \""+picUrl+"\", \n" +
                "        \"messageUrl\": \""+messageUrl+"\"\n" +
                "    }\n" +
                "}";
        dealDingDingMsgSend(accessToken, textMsg);
    }

    /**
     * markdown类型
     * @param accessToken
     * @param title
     * @param text
     * @param atMobiles
     */
    public static void sendDingDingMarkdownGroupMsg(String accessToken, String secret, String title, String text, String atMobiles) {
        log.info("【发送钉钉群消息】正在发送markdown类型的钉钉消息...");
        JSONObject markdown = new JSONObject();
        markdown.put("title", title);
        markdown.put("text", text);

        JSONObject at = new JSONObject();
        at.put("atMobiles", atMobiles);
        at.put("isAtAll", false);

        JSONObject textMsg = new JSONObject();
        textMsg.put("msgtype", "markdown");
        textMsg.put("markdown", markdown);
        textMsg.put("at", at);

        dealDingDingMsgSendNew(accessToken, secret, textMsg.toJSONString());
    }

    /**
     * 整体跳转ActionCard类型
     * @param accessToken
     * @param title
     * @param text
     * @param singleTitle
     * @param singleURL
     */
    public static void sendDingDingActionCardGroupMsg(String accessToken, String title, String text, String singleTitle, String singleURL) {
        String textMsg = "{\n" +
                "    \"actionCard\": {\n" +
                "        \"title\": \""+title+"\", \n" +
                "        \"text\": \"![screenshot](https://mmbiz.qpic.cn/mmbiz_jpg/jyPD8edcUjEwQ1Tdotpq94VE4G1wIMAxQyI2Oe7RaDRT0iaBRD2KdOL0iaL56jBWQX5Fzq3S7R66pyuEIZW83Ulw/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)"+text+"\", \n" +
                "        \"hideAvatar\": \"0\", \n" +
                "        \"btnOrientation\": \"0\", \n" +
                "        \"singleTitle\" : \""+singleTitle+"\",\n" +
                "        \"singleURL\" : \""+singleURL+"\"\n" +
                "    }, \n" +
                "    \"msgtype\": \"actionCard\"\n" +
                "}";
        dealDingDingMsgSend(accessToken, textMsg);
    }

    /**
     * 独立跳转ActionCard类型
     * @param accessToken
     * @param title
     * @param text
     * @param singleTitle
     * @param singleURL
     */
    public static void sendDingDingActionCardGroupMsg2(String accessToken, String title, String text, String singleTitle, String singleURL) {
        String textMsg = "{\n" +
                "    \"actionCard\": {\n" +
                "        \"title\": \"乔布斯 20 年前想打造一间苹果咖啡厅，而它正是 Apple Store 的前身\", \n" +
                "        \"text\": \"![screenshot](@lADOpwk3K80C0M0FoA) \n" +
                " ### 乔布斯 20 年前想打造的苹果咖啡厅 \n" +
                " Apple Store 的设计正从原来满满的科技感走向生活化，而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划\", \n" +
                "        \"hideAvatar\": \"0\", \n" +
                "        \"btnOrientation\": \"0\", \n" +
                "        \"btns\": [\n" +
                "            {\n" +
                "                \"title\": \"内容不错\", \n" +
                "                \"actionURL\": \"https://www.dingtalk.com/\"\n" +
                "            }, \n" +
                "            {\n" +
                "                \"title\": \"不感兴趣\", \n" +
                "                \"actionURL\": \"https://www.dingtalk.com/\"\n" +
                "            }\n" +
                "        ]\n" +
                "    }, \n" +
                "    \"msgtype\": \"actionCard\"\n" +
                "}\n";
        dealDingDingMsgSend(accessToken, textMsg);
    }

    /**
     * FeedCard类型
     * @param accessToken
     * @param title
     * @param text
     * @param singleTitle
     * @param singleURL
     */
    public static void sendDingDingFeedCardGroupMsg(String accessToken, String title, String text, String singleTitle, String singleURL) {
        String textMsg = "{\n" +
                "    \"feedCard\": {\n" +
                "        \"links\": [\n" +
                "            {\n" +
                "                \"title\": \"时代的火车向前开\", \n" +
                "                \"messageURL\": \"https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI\", \n" +
                "                \"picURL\": \"https://www.dingtalk.com/\"\n" +
                "            },\n" +
                "            {\n" +
                "                \"title\": \"时代的火车向前开2\", \n" +
                "                \"messageURL\": \"https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI\", \n" +
                "                \"picURL\": \"https://www.dingtalk.com/\"\n" +
                "            }\n" +
                "        ]\n" +
                "    }, \n" +
                "    \"msgtype\": \"feedCard\"\n" +
                "}";
        dealDingDingMsgSend(accessToken, textMsg);
    }

    /**
     * 发送钉钉群消息（可以艾特人）- 技术专用
     * @param content 发送内容
     */
    public static void sendDingDingGroupMsg(String content){
        sendDingDingGroupMsg(DingTokenEnum.SEND_SMS_BY_DEVELOPER_TOKEN.getToken(), content, DingMsgPhoneEnum.DEVELOPER_PHONE.getPhone());
    }


    public static void main(String[] args) {
//        sendDingDingGroupMsg(DingTokenEnum.SEND_SMS_BY_DEVELOPER_TOKEN.getToken(), "【系统消息】钉钉消息推送测试，by:songfayuan...", DingMsgPhoneEnum.DEVELOPER_PHONE.getPhone());
//        sendDingDingLinkGroupMsg(DingTokenEnum.SEND_SMS_BY_DEVELOPER_TOKEN.getToken(), "【系统消息】", "我喜欢，驾驭着代码在风驰电掣中创造完美！我喜欢，操纵着代码在随心所欲中体验生活！我喜欢，书写着代码在时代浪潮中完成经典！每一段新的代码在我手中诞生对我来说就象观看刹那花开的感动！", "https://blog.csdn.net/u011019141/static/img/homepage_icon_welcome.b870f20.jpg", "https://blog.csdn.net/u011019141");

//        String title = "杭州天气";
//        String text = "#### 杭州天气 @138*****41\n" +
//                "> 9度，西北风1级，空气良89，相对温度73%\n\n" +
//                "> ![screenshot](http://i.weather.com.cn/images/cn/news/2019/10/23/1571815463327062988.jpg)\n"  +
//                "> ###### 10点20分发布 [天气](http://www.weather.com.cn/weather/101210101.shtml) \n";
//        String atMobiles = "[138*****41,156*****57,150*****011]";
//        sendDingDingMarkdownGroupMsg(DingTokenEnum.SEND_SMS_BY_MARKDOWN_TOKEN.getToken(), DingTokenEnum.SEND_SMS_BY_MARKDOWN_TOKEN.getSecret(),title, text, atMobiles);

        sendDingDingGroupMsg(DingTokenEnum.SEND_SMS_TEST_TOKEN.getToken(),"服务测试消息。。。。。。。。。");
//        sendDingDingActionCardGroupMsg(DingTokenEnum.SEND_SMS_BY_DEVELOPER_TOKEN.getToken(), "【系统消息】", "2323", "阅读全文", "https://blog.csdn.net/u011019141");
//        sendDingDingActionCardGroupMsg2(DingTokenEnum.SEND_SMS_BY_DEVELOPER_TOKEN.getToken(), "【系统消息】", "2323", "阅读全文", "https://blog.csdn.net/u011019141");
//        sendDingDingFeedCardGroupMsg(DingTokenEnum.SEND_SMS_BY_DEVELOPER_TOKEN.getToken(), "【系统消息】", "2323", "阅读全文", "https://blog.csdn.net/u011019141");
    }
}
